package errs

import (
	"errors"
	"fmt"
	"gorm.io/gorm"
	"net/http"
	"runtime"
)

type Error struct {
	Stack   string      //栈信息，存报错位置
	Code    int         // 自定义错误码，如 10001（业务错误），50001（系统错误）
	Msg     string      // 用户可读的提示信息
	Cause   error       // 内部错误（可追踪）
	Details interface{} // 可选字段，存放更多上下文
}

func (e *Error) Error() string {
	if e.Cause != nil {
		return fmt.Sprintf("err_code=%d, msg=%s, cause=%v", e.Code, e.Msg, e.Cause)
	}
	return fmt.Sprintf("err_code=%d, msg=%s", e.Code, e.Msg)
}

func (e *Error) Unwrap() error {
	return e.Cause
}

func New(code int, msg string) error {
	// 生成堆栈信息
	buf := make([]byte, 1024)
	runtime.Stack(buf, false)
	return &Error{Stack: string(buf), Code: code, Msg: msg}
}

func Def(msg string, cause error) error {
	// 生成堆栈信息
	buf := make([]byte, 1024)
	runtime.Stack(buf, false)
	return &Error{Stack: string(buf), Code: http.StatusInternalServerError, Msg: msg, Cause: cause}
}

func Wrap(code int, msg string, cause error) error {
	// 生成堆栈信息
	buf := make([]byte, 1024)
	runtime.Stack(buf, false)
	return &Error{Stack: string(buf), Code: code, Msg: msg, Cause: cause}
}

func ErrNotFound(cause error) error {
	if cause == nil || errors.Is(cause, gorm.ErrRecordNotFound) {
		return nil
	} else {
		return Wrap(http.StatusAccepted, fmt.Sprintf("数据库操作失败：%s", cause.Error()), cause)
	}
}
